
class Vector3 {
    x: number;
    y: number;
    z: number;
    constructor(v3?: Vector3 | number, b?: number, c?: number) {
        if (v3 && b && c) {
            this.x = <number>v3;
            this.y = b;
            this.z = c;
        } else if (v3) {
            this.x = (<Vector3>v3).x;
            this.y = (<Vector3>v3).y;
            this.z = (<Vector3>v3).z;
        }
    }
    Copy(v3: Vector3): Vector3 {
        this.x = v3.x;
        this.y = v3.y;
        this.z = v3.z;
        return this;
    }
    Equal(v3: Vector3): boolean {
        return this.x == v3.x && this.y == v3.y && this.z == v3.z;
    }
    NotEqual(v: Vector3): boolean {
        return !this.Equal(v);
    }
    SetZero() {
        this.x = 0;
        this.y = 0;
        this.z = 0;
    }
    Negative(): Vector3 {
        return new Vector3(-this.x, -this.y, -this.z);
    }
    Add(v: Vector3): Vector3 {
        return new Vector3(this.x + v.x, this.y + v.y, this.z + v.z);
    }
    Subtraction(v: Vector3): Vector3 {
        return new Vector3(this.x - v.x, this.y - v.y, this.z - v.z);
    }
    MultiScalar(n: number): Vector3 {
        return new Vector3(this.x * n, this.y * n, this.z * n);
    }
    DivisScalar(n: number): Vector3 {
        if (n != 0) {
            let oneOverN = 1.0 / n;
            return this.MultiScalar(oneOverN);
        }
        return this;
    }
    Normalize(): Vector3 {
        let magSq = this.x * this.x + this.y * this.y + this.z * this.z;
        if (magSq > 0) {
            let oneOverMag = 1.0 / Math.sqrt(magSq);
            this.x = this.x * oneOverMag;
            this.y = this.y * oneOverMag;
            this.z = this.z * oneOverMag;
        }
        return this;
    }
    MultiDot(v: Vector3): Vector3 {
        return new Vector3(this.x * v.x, this.y * v.y, this.z * v.z);
    }
    MultiCross(b: Vector3): Vector3 {
        return new Vector3(
            this.y * b.z - this.z * b.y,
            this.z * b.x - this.x * b.z,
            this.x * b.y - this.y * b.x
        )
    }
    Mag(): number {
        return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
    }
    Distance(v: Vector3): number {
        let dx = this.x - v.x;
        let dy = this.y - v.y;
        let dz = this.z - v.z;
        return Math.sqrt(dx * dx + dy * dy + dz * dz);
    }

}